{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Split Learning—Bank Marketing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ">The following codes are demos only. It's **NOT for production** due to system security concerns, please **DO NOT** use it directly in production."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this tutorial, we will use the bank's marketing model as an example to show how to accomplish split learning in vertical scenarios under the `SecretFlow` framework.\n",
    "`SecretFlow` provides a user-friendly Api that makes it easy to apply your Keras model or PyTorch model to split learning scenarios to complete joint modeling tasks for vertical scenarios.\n",
    "\n",
    "In this tutorial we will show you how to turn your existing 'Keras' model into a split learning model under `Secretflow` to complete federated multi-party modeling tasks."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What is Split Learning？"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The core idea of split learning is to split the network structure. Each device (silo) retains only a part of the network structure, and the sub-network structure of all devices is combined together to form a complete network model. \n",
    "In the training process, different devices (silos) only perform forward or reverse calculation on the local network structure, and transfer the calculation results to the next device. Multiple devices complete the training through joint model until convergence.\n",
    "\n",
    " <img alt=\"split_learning_tutorial.png\" src=\"resources/split_learning_tutorial.png\" width=\"600\">  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Alice**：have *data\\_alice*，*model\\_base\\_alice*  \n",
    "**Bob**: have *data\\_bob*，*model\\_base\\_bob*，*model\\_fuse*  \n",
    "\n",
    "1. **Alice** uses its data to get *hidden0* through *model\\_base\\_Alice* and send it to Bob. \n",
    "2. **Bob** gets *hidden1* with its data through *model\\_base\\_bob*.\n",
    "3. *hidden\\_0* and *hidden\\_1* are input to the *AggLayer* for aggregation, and the aggregated *hidden\\_merge* is the output.\n",
    "4. **Bob** input *hidden\\_merge* to *model\\_fuse*, get the gradient with *label* and send it back.\n",
    "5. The gradient is split into two parts *g\\_0*, *g\\_1* through *AggLayer*, which are sent to **Alice** and **Bob** respectively.\n",
    "6. Then **Alice** and **Bob** update their local base net with *g\\_0* or *g\\_1*.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Task"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Marketing is the banking industry in the ever-changing market environment, to meet the needs of customers, to achieve business objectives of the overall operation and sales activities. In the current environment of big data, data analysis provides a more effective analysis means for the banking industry. Customer demand analysis, understanding of target market trends and more macro market strategies can provide the basis and direction.  \n",
    "  \n",
    "The data from [kaggle](https://www.kaggle.com/janiobachmann/bank-marketing-dataset) is a set of classic marketing data bank, is a Portuguese bank agency telephone direct marketing activities, The target variable is whether the customer subscribes to deposit product."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data\n",
    "\n",
    "1. The total sample size was 11162, including 8929 training set and 2233 test set\n",
    "2. Feature dim is 16, target is binary classification\n",
    "3. We have cut the data in advance. Alice holds the 4-dimensional basic attribute features, Bob holds the 12-dimensional bank transaction features, and only Alice holds the corresponding label"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's start by looking at what our bank's marketing data look like?  \n",
    "\n",
    "The original data is divided into Bank Alice and Bank Bob, which stores in Alice and Bob respectively. Here, CSV is the original data that has only been separated without pre-processing, we will use `secretflow preprocess` for FedData preprocess"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:20:52.540750Z",
     "end_time": "2023-04-24T10:20:58.618980Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2023-04-24 10:20:58,140\tINFO worker.py:1538 -- Started a local Ray instance.\n"
     ]
    }
   ],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "import secretflow as sf\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "sf.shutdown()\n",
    "sf.init(['alice', 'bob'], address='local')\n",
    "alice, bob = sf.PYU('alice'), sf.PYU('bob')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### prepare data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:20:58.610952Z",
     "end_time": "2023-04-24T10:20:58.722704Z"
    }
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from secretflow.utils.simulation.datasets import dataset\n",
    "\n",
    "df = pd.read_csv(dataset('bank_marketing'), sep=';')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We assume that Alice is a new bank, and they only have the basic information of the user and purchased the label of financial products from other bank."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:20:58.721903Z",
     "end_time": "2023-04-24T10:20:58.764321Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "      age            job  marital  education   y\n0      30     unemployed  married    primary  no\n1      33       services  married  secondary  no\n2      35     management   single   tertiary  no\n3      30     management  married   tertiary  no\n4      59    blue-collar  married  secondary  no\n...   ...            ...      ...        ...  ..\n4516   33       services  married  secondary  no\n4517   57  self-employed  married   tertiary  no\n4518   57     technician  married  secondary  no\n4519   28    blue-collar  married  secondary  no\n4520   44   entrepreneur   single   tertiary  no\n\n[4521 rows x 5 columns]",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>age</th>\n      <th>job</th>\n      <th>marital</th>\n      <th>education</th>\n      <th>y</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>30</td>\n      <td>unemployed</td>\n      <td>married</td>\n      <td>primary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>33</td>\n      <td>services</td>\n      <td>married</td>\n      <td>secondary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>35</td>\n      <td>management</td>\n      <td>single</td>\n      <td>tertiary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>30</td>\n      <td>management</td>\n      <td>married</td>\n      <td>tertiary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>59</td>\n      <td>blue-collar</td>\n      <td>married</td>\n      <td>secondary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>...</th>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n    </tr>\n    <tr>\n      <th>4516</th>\n      <td>33</td>\n      <td>services</td>\n      <td>married</td>\n      <td>secondary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>4517</th>\n      <td>57</td>\n      <td>self-employed</td>\n      <td>married</td>\n      <td>tertiary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>4518</th>\n      <td>57</td>\n      <td>technician</td>\n      <td>married</td>\n      <td>secondary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>4519</th>\n      <td>28</td>\n      <td>blue-collar</td>\n      <td>married</td>\n      <td>secondary</td>\n      <td>no</td>\n    </tr>\n    <tr>\n      <th>4520</th>\n      <td>44</td>\n      <td>entrepreneur</td>\n      <td>single</td>\n      <td>tertiary</td>\n      <td>no</td>\n    </tr>\n  </tbody>\n</table>\n<p>4521 rows × 5 columns</p>\n</div>"
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alice_data = df[[\"age\", \"job\", \"marital\", \"education\", \"y\"]]\n",
    "alice_data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Bob is an old bank, they have the user's account balance, house, loan, and recent marketing feedback"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:20:58.746285Z",
     "end_time": "2023-04-24T10:20:58.901868Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "     default  balance housing loan   contact  day month  duration  campaign  \\\n0         no     1787      no   no  cellular   19   oct        79         1   \n1         no     4789     yes  yes  cellular   11   may       220         1   \n2         no     1350     yes   no  cellular   16   apr       185         1   \n3         no     1476     yes  yes   unknown    3   jun       199         4   \n4         no        0     yes   no   unknown    5   may       226         1   \n...      ...      ...     ...  ...       ...  ...   ...       ...       ...   \n4516      no     -333     yes   no  cellular   30   jul       329         5   \n4517     yes    -3313     yes  yes   unknown    9   may       153         1   \n4518      no      295      no   no  cellular   19   aug       151        11   \n4519      no     1137      no   no  cellular    6   feb       129         4   \n4520      no     1136     yes  yes  cellular    3   apr       345         2   \n\n      pdays  previous poutcome  \n0        -1         0  unknown  \n1       339         4  failure  \n2       330         1  failure  \n3        -1         0  unknown  \n4        -1         0  unknown  \n...     ...       ...      ...  \n4516     -1         0  unknown  \n4517     -1         0  unknown  \n4518     -1         0  unknown  \n4519    211         3    other  \n4520    249         7    other  \n\n[4521 rows x 12 columns]",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>default</th>\n      <th>balance</th>\n      <th>housing</th>\n      <th>loan</th>\n      <th>contact</th>\n      <th>day</th>\n      <th>month</th>\n      <th>duration</th>\n      <th>campaign</th>\n      <th>pdays</th>\n      <th>previous</th>\n      <th>poutcome</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>no</td>\n      <td>1787</td>\n      <td>no</td>\n      <td>no</td>\n      <td>cellular</td>\n      <td>19</td>\n      <td>oct</td>\n      <td>79</td>\n      <td>1</td>\n      <td>-1</td>\n      <td>0</td>\n      <td>unknown</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>no</td>\n      <td>4789</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>cellular</td>\n      <td>11</td>\n      <td>may</td>\n      <td>220</td>\n      <td>1</td>\n      <td>339</td>\n      <td>4</td>\n      <td>failure</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>no</td>\n      <td>1350</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>cellular</td>\n      <td>16</td>\n      <td>apr</td>\n      <td>185</td>\n      <td>1</td>\n      <td>330</td>\n      <td>1</td>\n      <td>failure</td>\n    </tr>\n    <tr>\n      <th>3</th>\n      <td>no</td>\n      <td>1476</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>unknown</td>\n      <td>3</td>\n      <td>jun</td>\n      <td>199</td>\n      <td>4</td>\n      <td>-1</td>\n      <td>0</td>\n      <td>unknown</td>\n    </tr>\n    <tr>\n      <th>4</th>\n      <td>no</td>\n      <td>0</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>unknown</td>\n      <td>5</td>\n      <td>may</td>\n      <td>226</td>\n      <td>1</td>\n      <td>-1</td>\n      <td>0</td>\n      <td>unknown</td>\n    </tr>\n    <tr>\n      <th>...</th>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n      <td>...</td>\n    </tr>\n    <tr>\n      <th>4516</th>\n      <td>no</td>\n      <td>-333</td>\n      <td>yes</td>\n      <td>no</td>\n      <td>cellular</td>\n      <td>30</td>\n      <td>jul</td>\n      <td>329</td>\n      <td>5</td>\n      <td>-1</td>\n      <td>0</td>\n      <td>unknown</td>\n    </tr>\n    <tr>\n      <th>4517</th>\n      <td>yes</td>\n      <td>-3313</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>unknown</td>\n      <td>9</td>\n      <td>may</td>\n      <td>153</td>\n      <td>1</td>\n      <td>-1</td>\n      <td>0</td>\n      <td>unknown</td>\n    </tr>\n    <tr>\n      <th>4518</th>\n      <td>no</td>\n      <td>295</td>\n      <td>no</td>\n      <td>no</td>\n      <td>cellular</td>\n      <td>19</td>\n      <td>aug</td>\n      <td>151</td>\n      <td>11</td>\n      <td>-1</td>\n      <td>0</td>\n      <td>unknown</td>\n    </tr>\n    <tr>\n      <th>4519</th>\n      <td>no</td>\n      <td>1137</td>\n      <td>no</td>\n      <td>no</td>\n      <td>cellular</td>\n      <td>6</td>\n      <td>feb</td>\n      <td>129</td>\n      <td>4</td>\n      <td>211</td>\n      <td>3</td>\n      <td>other</td>\n    </tr>\n    <tr>\n      <th>4520</th>\n      <td>no</td>\n      <td>1136</td>\n      <td>yes</td>\n      <td>yes</td>\n      <td>cellular</td>\n      <td>3</td>\n      <td>apr</td>\n      <td>345</td>\n      <td>2</td>\n      <td>249</td>\n      <td>7</td>\n      <td>other</td>\n    </tr>\n  </tbody>\n</table>\n<p>4521 rows × 12 columns</p>\n</div>"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bob_data = df[[\"default\", \"balance\", \"housing\", \"loan\", \"contact\", \n",
    "             \"day\",\"month\",\"duration\",\"campaign\",\"pdays\",\"previous\",\"poutcome\"]]\n",
    "bob_data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create Secretflow Environment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create 2 entities in the Secretflow environment [Alice, Bob]\n",
    "Where 'Alice' and 'Bob' are two PYU\n",
    "Once you've constructed the two objects, you can happily start Splitting Learning"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Import Dependency"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:20:58.799320Z",
     "end_time": "2023-04-24T10:21:00.546979Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2023-04-24 10:20:59.841732: E tensorflow/stream_executor/cuda/cuda_blas.cc:2981] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
      "2023-04-24 10:21:00.576963: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory\n",
      "2023-04-24 10:21:00.577064: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory\n",
      "2023-04-24 10:21:00.577078: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n"
     ]
    }
   ],
   "source": [
    "from secretflow.data.split import train_test_split\n",
    "from secretflow.ml.nn import SLModel"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Prepare Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Build Federated Table**\n",
    "\n",
    "\n",
    "Federated table is a virtual concept that cross multiple parties, We define `VDataFrame` for vertical setting\n",
    "\n",
    "1. The data of all parties in a federated table is stored locally and is not allowed to go out of the domain.\n",
    "\n",
    "2. No one has access to data store except the party that owns the data.\n",
    "\n",
    "3. Any operation of the federated table will be scheduled by the driver to each worker, and the execution instructions will be delivered layer by layer until the Python Runtime of the specific worker. The framework ensures that only `worker.device` and `Object`. device can operate data at the same time.\n",
    "\n",
    "4. Federated tables are designed to management and manipulation multi-party data from a central perspective.\n",
    "\n",
    "5. Interfaces to `Federated Table` are aligned to `pandas.DataFrame` to reduce the cost of multi-party data operations.\n",
    "\n",
    "6. The SecretFlow framework provides Plain&Ciphertext hybrid programming capabilities. Vertical federated tables are built using `SPU`, and `MPC-PSI` is used to safely get intersection and align data from all parties.\n",
    "\n",
    "<img alt=\"vdataframe.png\" src=\"resources/vdataframe.png\" width=\"600\">  \n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "VDataFrame provides `read_csv` interface similar to pandas, except that `secretflow.read_csv` receives a dictionary that defines the path of data for both parties. We can use `secretflow.vertical.read_csv` to build the `VDataFrame`.\n",
    "```\n",
    "read_csv(file_dict,delimiter,ppu,keys,drop_key)\n",
    "    filepath: Path of the participant file. The address can be a relative or absolute path to a local file\n",
    "    ppu: PPU Device for PSI; If this parameter is not specified, data must be prealigned\n",
    "    keys: Key for intersection\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create spu object"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:00.573860Z",
     "end_time": "2023-04-24T10:21:00.634898Z"
    }
   },
   "outputs": [],
   "source": [
    "spu = sf.SPU(sf.utils.testing.cluster_def(['alice', 'bob']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:00.659211Z",
     "end_time": "2023-04-24T10:21:00.780683Z"
    }
   },
   "outputs": [],
   "source": [
    "from secretflow.utils.simulation.datasets import load_bank_marketing\n",
    "\n",
    "# Alice has the first four features,\n",
    "# while bob has the left features\n",
    "data = load_bank_marketing(parts={alice: (0, 4), bob: (4, 16)}, axis=1)\n",
    "# Alice holds the label.\n",
    "label = load_bank_marketing(parts={alice: (16, 17)}, axis=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`data` is a vertically federated table. It only has the `Schema` of all the data globally"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's take a closer look at VDF data management \n",
    "\n",
    "As can be seen from an example, the `age` field belongs to Alice, so the corresponding column can be obtained in the partition of Alice, but Bob will report `KeyError` error when trying to obtain age.  \n",
    "There is a concept of `Partition`, which is a data fragment defined by us. Each Partition has its own device to which it belongs, and only the device that belongs can operate data."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:00.771681Z",
     "end_time": "2023-04-24T10:21:02.113978Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "<secretflow.device.device.pyu.PYUObject at 0x7fb54bc6d250>"
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data['age'].partitions[alice].data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:02.110945Z",
     "end_time": "2023-04-24T10:21:02.172944Z"
    }
   },
   "outputs": [],
   "source": [
    "# You can uncomment this and you will get a KeyError.\n",
    "# data['age'].partitions[bob]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We then do data preprocessing on the `VDataFrame`.。  \n",
    "Here we take `LabelEncoder` and `MinMaxScaler` as examples. These two preprocessor functions have corresponding concepts in `SkLearn` and their use methods are similar to those in `SkLearn`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:02.179947Z",
     "end_time": "2023-04-24T10:21:02.235531Z"
    }
   },
   "outputs": [],
   "source": [
    "from secretflow.preprocessing.scaler import MinMaxScaler\n",
    "from secretflow.preprocessing.encoder import LabelEncoder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:02.234534Z",
     "end_time": "2023-04-24T10:21:04.183444Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001B[2m\u001B[36m(SPURuntime pid=240157)\u001B[0m 2023-04-24 10:21:03.623 [error] [context.cc:operator():132] connect to rank=0 failed with error [external/yacl/yacl/link/transport/channel_brpc.cc:368] send, rpc failed=112, message=[E111]Fail to connect Socket{id=0 addr=127.0.0.1:34003} (0x0x4821fc0): Connection refused [R1][E112]Not connected to 127.0.0.1:34003 yet, server_id=0 [R2][E112]Not connected to 127.0.0.1:34003 yet, server_id=0 [R3][E112]Not connected to 127.0.0.1:34003 yet, server_id=0\n"
     ]
    }
   ],
   "source": [
    "encoder = LabelEncoder()\n",
    "data['job'] = encoder.fit_transform(data['job'])\n",
    "data['marital'] = encoder.fit_transform(data['marital'])\n",
    "data['education'] = encoder.fit_transform(data['education'])\n",
    "data['default'] = encoder.fit_transform(data['default'])\n",
    "data['housing'] = encoder.fit_transform(data['housing'])\n",
    "data['loan'] = encoder.fit_transform(data['loan'])\n",
    "data['contact'] = encoder.fit_transform(data['contact'])\n",
    "data['poutcome'] = encoder.fit_transform(data['poutcome'])\n",
    "data['month'] = encoder.fit_transform(data['month'])\n",
    "label = encoder.fit_transform(label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:04.183444Z",
     "end_time": "2023-04-24T10:21:04.225413Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "label= <class 'secretflow.data.vertical.dataframe.VDataFrame'>,\n",
      "data = <class 'secretflow.data.vertical.dataframe.VDataFrame'>\n"
     ]
    }
   ],
   "source": [
    "print(f\"label= {type(label)},\\ndata = {type(data)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Standardize data via MinMaxScaler"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:04.230378Z",
     "end_time": "2023-04-24T10:21:04.361376Z"
    }
   },
   "outputs": [],
   "source": [
    "scaler = MinMaxScaler()\n",
    "\n",
    "data = scaler.fit_transform(data)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we divide the data set into train-set and test-set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:04.354410Z",
     "end_time": "2023-04-24T10:21:04.428427Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001B[2m\u001B[36m(_run pid=239859)\u001B[0m /home/limingbo/.conda/envs/sf/lib/python3.8/site-packages/sklearn/base.py:443: UserWarning: X has feature names, but MinMaxScaler was fitted without feature names\n",
      "\u001B[2m\u001B[36m(_run pid=239859)\u001B[0m   warnings.warn(\n",
      "\u001B[2m\u001B[36m(_run pid=239859)\u001B[0m /home/limingbo/.conda/envs/sf/lib/python3.8/site-packages/sklearn/base.py:443: UserWarning: X has feature names, but MinMaxScaler was fitted without feature names\n",
      "\u001B[2m\u001B[36m(_run pid=239859)\u001B[0m   warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "from secretflow.data.split import train_test_split\n",
    "random_state = 1234\n",
    "train_data,test_data = train_test_split(data, train_size=0.8, random_state=random_state)\n",
    "train_label,test_label = train_test_split(label, train_size=0.8, random_state=random_state)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Summary:** At this point, we have completed the definition of **federated tables**, **data preprocessing**, and **training set and test set partitioning**\n",
    "The secretFlow framework defines a set of operations to be built on the federated table (its logical counterpart is `pandas.DataFrame`). The secretflow framework defines a set of operations to be built on the federated table (its logical counterpart is `sklearn`) Refer to our documentation and API introduction to learn more about other features"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduce Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**local version**: \n",
    "For this task, a basic DNN can be completed, input 16-dimensional features, through a DNN network, output the probability of positive and negative samples.\n",
    "\n",
    "\n",
    "**Federate version**：\n",
    "* Alice：\n",
    "    - base_net: Input 4-dimensional feature and go through a DNN network to get hidden\n",
    "    - fuse_net: Receive hidden features calculated by Alice and Bob, input them to FUSENET for feature fusion, and complete the forward process and backward process\n",
    "* Bob：\n",
    "    - base_net: Input 12-dimensional features, get hidden through a DNN network, and then send hidden to Alice to complete the following operation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define Model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we start creating the federated model \n",
    "we define SLTFModel and SLTorchModel(WIP), which are used to build split learning of vertical scene. We define a simple and easy to use extensible interface, which can easily transform your existing Model into SF-Model, and then conduct vertical scene federation modeling"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Split learning is to break up a model so that one part is executed locally on the data and the other part is executed on the label side.\n",
    "First let's define the locally executed model -- base_model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:04.423376Z",
     "end_time": "2023-04-24T10:21:04.509376Z"
    }
   },
   "outputs": [],
   "source": [
    "def create_base_model(input_dim, output_dim,  name='base_model'):\n",
    "    # Create model\n",
    "    def create_model():\n",
    "        from tensorflow import keras\n",
    "        from tensorflow.keras import layers\n",
    "        import tensorflow as tf\n",
    "        model = keras.Sequential(\n",
    "            [\n",
    "                keras.Input(shape=input_dim),\n",
    "                layers.Dense(100,activation =\"relu\" ),\n",
    "                layers.Dense(output_dim, activation=\"relu\"),\n",
    "            ]\n",
    "        )\n",
    "        # Compile model\n",
    "        model.summary()\n",
    "        model.compile(loss='binary_crossentropy',\n",
    "                      optimizer='adam',\n",
    "                      metrics=[\"accuracy\",tf.keras.metrics.AUC()])\n",
    "        return model\n",
    "    return create_model\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We use create_base_model to create their base models for 'Alice' and 'Bob', respectively"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:04.498376Z",
     "end_time": "2023-04-24T10:21:04.562202Z"
    }
   },
   "outputs": [],
   "source": [
    "# prepare model\n",
    "hidden_size = 64\n",
    "# get the number of features of each party.\n",
    "# When the input data changes, the network automatically adjusts to the input data\n",
    "alice_input_feature_num = train_data.values.partition_shape()[alice][1]\n",
    "bob_input_feature_num = train_data.values.partition_shape()[bob][1]\n",
    "\n",
    "model_base_alice = create_base_model(alice_input_feature_num, hidden_size)\n",
    "model_base_bob = create_base_model(bob_input_feature_num, hidden_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:04.561376Z",
     "end_time": "2023-04-24T10:21:08.529104Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      " Layer (type)                Output Shape              Param #   \n",
      "=================================================================\n",
      " dense (Dense)               (None, 100)               500       \n",
      "                                                                 \n",
      " dense_1 (Dense)             (None, 64)                6464      \n",
      "                                                                 \n",
      "=================================================================\n",
      "Total params: 6,964\n",
      "Trainable params: 6,964\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "Model: \"sequential_1\"\n",
      "_________________________________________________________________\n",
      " Layer (type)                Output Shape              Param #   \n",
      "=================================================================\n",
      " dense_2 (Dense)             (None, 100)               1300      \n",
      "                                                                 \n",
      " dense_3 (Dense)             (None, 64)                6464      \n",
      "                                                                 \n",
      "=================================================================\n",
      "Total params: 7,764\n",
      "Trainable params: 7,764\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    },
    {
     "data": {
      "text/plain": "<keras.engine.sequential.Sequential at 0x7fb54bc6d610>"
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_base_alice()\n",
    "model_base_bob()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next we define the side with the label, or the server-side model -- fuse_model\n",
    "In the definition of fuse_model, we need to correctly define `loss`, `optimizer`, and `metrics`. This is compatible with all configurations of your existing Keras model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:08.516084Z",
     "end_time": "2023-04-24T10:21:08.567138Z"
    }
   },
   "outputs": [],
   "source": [
    "def create_fuse_model(input_dim, output_dim, party_nums, name='fuse_model'):\n",
    "    def create_model():\n",
    "        from tensorflow import keras\n",
    "        from tensorflow.keras import layers\n",
    "        import tensorflow as tf\n",
    "        # input\n",
    "        input_layers = []\n",
    "        for i in range(party_nums):\n",
    "            input_layers.append(keras.Input(input_dim,))\n",
    "        \n",
    "        merged_layer = layers.concatenate(input_layers)\n",
    "        fuse_layer = layers.Dense(64, activation='relu')(merged_layer)\n",
    "        output = layers.Dense(output_dim, activation='sigmoid')(fuse_layer)\n",
    "\n",
    "        model = keras.Model(inputs=input_layers, outputs=output)\n",
    "        model.summary()\n",
    "        \n",
    "        model.compile(loss='binary_crossentropy',\n",
    "                      optimizer='adam',\n",
    "                      metrics=[\"accuracy\",tf.keras.metrics.AUC()])\n",
    "        return model\n",
    "    return create_model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:08.553106Z",
     "end_time": "2023-04-24T10:21:08.567138Z"
    }
   },
   "outputs": [],
   "source": [
    "model_fuse = create_fuse_model(\n",
    "    input_dim=hidden_size, party_nums=2, output_dim=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:08.556071Z",
     "end_time": "2023-04-24T10:21:08.709104Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"model\"\n",
      "__________________________________________________________________________________________________\n",
      " Layer (type)                   Output Shape         Param #     Connected to                     \n",
      "==================================================================================================\n",
      " input_3 (InputLayer)           [(None, 64)]         0           []                               \n",
      "                                                                                                  \n",
      " input_4 (InputLayer)           [(None, 64)]         0           []                               \n",
      "                                                                                                  \n",
      " concatenate (Concatenate)      (None, 128)          0           ['input_3[0][0]',                \n",
      "                                                                  'input_4[0][0]']                \n",
      "                                                                                                  \n",
      " dense_4 (Dense)                (None, 64)           8256        ['concatenate[0][0]']            \n",
      "                                                                                                  \n",
      " dense_5 (Dense)                (None, 1)            65          ['dense_4[0][0]']                \n",
      "                                                                                                  \n",
      "==================================================================================================\n",
      "Total params: 8,321\n",
      "Trainable params: 8,321\n",
      "Non-trainable params: 0\n",
      "__________________________________________________________________________________________________\n"
     ]
    },
    {
     "data": {
      "text/plain": "<keras.engine.functional.Functional at 0x7fb548506d00>"
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model_fuse()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create Split Learning Model\n",
    "Secretflow provides the split learning model `SLModel`\n",
    "To initial SLModel only need 3 parameters\n",
    "* base_model_dict: A dictionary needs to be passed in all clients participating in the training along with base_model mappings\n",
    "* device_y: PYU, which device has label\n",
    "* model_fuse: The fusion model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Define base_model_dict  \n",
    "```python\n",
    "base_model_dict:Dict[PYU,model_fn]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:08.702070Z",
     "end_time": "2023-04-24T10:21:08.747105Z"
    }
   },
   "outputs": [],
   "source": [
    "base_model_dict = {\n",
    "    alice: model_base_alice,\n",
    "    bob:   model_base_bob\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:08.747105Z",
     "end_time": "2023-04-24T10:21:08.769119Z"
    }
   },
   "outputs": [],
   "source": [
    "from secretflow.security.privacy import DPStrategy, GaussianEmbeddingDP, LabelDP\n",
    "\n",
    "# Define DP operations\n",
    "train_batch_size = 128\n",
    "gaussian_embedding_dp = GaussianEmbeddingDP(\n",
    "    noise_multiplier=0.5,\n",
    "    l2_norm_clip=1.0,\n",
    "    batch_size=train_batch_size,\n",
    "    num_samples=train_data.values.partition_shape()[alice][0],\n",
    "    is_secure_generator=False,\n",
    ")\n",
    "dp_strategy_alice = DPStrategy(embedding_dp=gaussian_embedding_dp)\n",
    "label_dp = LabelDP(eps=64.0)\n",
    "dp_strategy_bob = DPStrategy(label_dp=label_dp)\n",
    "dp_strategy_dict = {alice: dp_strategy_alice, bob: dp_strategy_bob}\n",
    "dp_spent_step_freq = 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:08.763071Z",
     "end_time": "2023-04-24T10:21:10.616673Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:Create proxy actor <class 'secretflow.ml.nn.sl.backend.tensorflow.sl_base.PYUSLTFModel'> with party alice.\n",
      "INFO:root:Create proxy actor <class 'secretflow.ml.nn.sl.backend.tensorflow.sl_base.PYUSLTFModel'> with party bob.\n"
     ]
    }
   ],
   "source": [
    "sl_model = SLModel(\n",
    "    base_model_dict=base_model_dict, \n",
    "    device_y=alice,  \n",
    "    model_fuse=model_fuse,\n",
    "    dp_strategy_dict=dp_strategy_dict,)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:10.616673Z",
     "end_time": "2023-04-24T10:21:10.676836Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "(           age       job  marital  education\n 1426  0.279412  0.181818      0.5   0.333333\n 416   0.176471  0.636364      1.0   0.333333\n 3977  0.264706  0.000000      0.5   0.666667\n 2291  0.338235  0.000000      0.5   0.333333\n 257   0.132353  0.909091      1.0   0.333333\n ...        ...       ...      ...        ...\n 1508  0.264706  0.818182      1.0   0.333333\n 979   0.544118  0.090909      0.0   0.000000\n 3494  0.455882  0.090909      0.5   0.000000\n 42    0.485294  0.090909      0.5   0.333333\n 1386  0.455882  0.636364      0.5   0.333333\n \n [905 rows x 4 columns],\n       y\n 1426  0\n 416   0\n 3977  0\n 2291  0\n 257   0\n ...  ..\n 1508  0\n 979   0\n 3494  0\n 42    0\n 1386  0\n \n [905 rows x 1 columns])"
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sf.reveal(test_data.partitions[alice].data), sf.reveal(test_label.partitions[alice].data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:10.676836Z",
     "end_time": "2023-04-24T10:21:10.741546Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "(           age       job  marital  education\n 1106  0.235294  0.090909      0.5   0.333333\n 1309  0.176471  0.363636      0.5   0.333333\n 2140  0.411765  0.272727      1.0   0.666667\n 2134  0.573529  0.454545      0.5   0.333333\n 960   0.485294  0.818182      0.5   0.333333\n ...        ...       ...      ...        ...\n 664   0.397059  0.090909      1.0   0.333333\n 3276  0.235294  0.181818      0.5   0.666667\n 1318  0.220588  0.818182      0.5   0.333333\n 723   0.220588  0.636364      0.5   0.333333\n 2863  0.176471  0.363636      1.0   0.666667\n \n [3616 rows x 4 columns],\n       y\n 1106  0\n 1309  0\n 2140  1\n 2134  0\n 960   0\n ...  ..\n 664   0\n 3276  0\n 1318  0\n 723   0\n 2863  0\n \n [3616 rows x 1 columns])"
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sf.reveal(train_data.partitions[alice].data), sf.reveal(train_label.partitions[alice].data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:10.740546Z",
     "end_time": "2023-04-24T10:21:24.716740Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:SL Train Params: {'self': <secretflow.ml.nn.sl.sl_model.SLModel object at 0x7fb548492910>, 'x': VDataFrame(partitions={alice: Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7fb54bc8ff10>), bob: Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7fb54bc8b970>)}, aligned=True), 'y': VDataFrame(partitions={alice: Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7fb54bc6cfd0>)}, aligned=True), 'batch_size': 128, 'epochs': 10, 'verbose': 1, 'callbacks': None, 'validation_data': (VDataFrame(partitions={alice: Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7fb54bc8f610>), bob: Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7fb54bc8b8e0>)}, aligned=True), VDataFrame(partitions={alice: Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7fb54bc6c970>)}, aligned=True)), 'shuffle': True, 'sample_weight': None, 'validation_freq': 1, 'dp_spent_step_freq': 10, 'dataset_builder': None, 'audit_log_dir': None, 'audit_log_params': {}, 'random_seed': 13780}\n",
      "\u001B[2m\u001B[36m(pid=240300)\u001B[0m 2023-04-24 10:21:13.143944: E tensorflow/stream_executor/cuda/cuda_blas.cc:2981] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
      "\u001B[2m\u001B[36m(pid=240309)\u001B[0m 2023-04-24 10:21:13.339222: E tensorflow/stream_executor/cuda/cuda_blas.cc:2981] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
      "\u001B[2m\u001B[36m(pid=240300)\u001B[0m 2023-04-24 10:21:13.923649: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory\n",
      "\u001B[2m\u001B[36m(pid=240300)\u001B[0m 2023-04-24 10:21:13.923745: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory\n",
      "\u001B[2m\u001B[36m(pid=240300)\u001B[0m 2023-04-24 10:21:13.923756: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n",
      "\u001B[2m\u001B[36m(pid=240309)\u001B[0m 2023-04-24 10:21:14.119980: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory\n",
      "\u001B[2m\u001B[36m(pid=240309)\u001B[0m 2023-04-24 10:21:14.120083: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory\n",
      "\u001B[2m\u001B[36m(pid=240309)\u001B[0m 2023-04-24 10:21:14.120095: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m 2023-04-24 10:21:16.143007: E tensorflow/stream_executor/cuda/cuda_driver.cc:265] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m 2023-04-24 10:21:16.357362: E tensorflow/stream_executor/cuda/cuda_driver.cc:265] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m Model: \"sequential\"\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m _________________________________________________________________\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  Layer (type)                Output Shape              Param #   \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m =================================================================\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  dense (Dense)               (None, 100)               500       \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m                                                                  \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  dense_1 (Dense)             (None, 64)                6464      \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m                                                                  \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m =================================================================\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m Total params: 6,964\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m Trainable params: 6,964\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m Non-trainable params: 0\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m _________________________________________________________________\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m Model: \"model\"\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m __________________________________________________________________________________________________\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  Layer (type)                   Output Shape         Param #     Connected to                     \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m ==================================================================================================\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  input_2 (InputLayer)           [(None, 64)]         0           []                               \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m                                                                                                   \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  input_3 (InputLayer)           [(None, 64)]         0           []                               \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m                                                                                                   \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  concatenate (Concatenate)      (None, 128)          0           ['input_2[0][0]',                \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m                                                                   'input_3[0][0]']                \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m                                                                                                   \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  dense_2 (Dense)                (None, 64)           8256        ['concatenate[0][0]']            \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m                                                                                                   \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m  dense_3 (Dense)                (None, 1)            65          ['dense_2[0][0]']                \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m                                                                                                   \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m ==================================================================================================\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m Total params: 8,321\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m Trainable params: 8,321\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m Non-trainable params: 0\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240300)\u001B[0m __________________________________________________________________________________________________\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  7%|▋         | 2/29 [00:00<00:02, 13.20it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m Model: \"sequential\"\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m _________________________________________________________________\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m  Layer (type)                Output Shape              Param #   \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m =================================================================\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m  dense (Dense)               (None, 100)               1300      \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m                                                                  \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m  dense_1 (Dense)             (None, 64)                6464      \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m                                                                  \n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m =================================================================\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m Total params: 7,764\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m Trainable params: 7,764\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m Non-trainable params: 0\n",
      "\u001B[2m\u001B[36m(PYUSLTFModel pid=240309)\u001B[0m _________________________________________________________________\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 29/29 [00:03<00:00,  9.22it/s, epoch: 1/10 -  train_loss:0.4876196086406708  train_accuracy:0.779037594795227  train_auc_1:0.523348331451416  val_loss:0.3805972635746002  val_accuracy:0.8729282021522522  val_auc_1:0.6476444602012634 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 42.60it/s, epoch: 2/10 -  train_loss:0.3252045810222626  train_accuracy:0.8960129022598267  train_auc_1:0.6373960375785828  val_loss:0.3656504452228546  val_accuracy:0.8729282021522522  val_auc_1:0.6615355014801025 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 42.80it/s, epoch: 3/10 -  train_loss:0.33422568440437317  train_accuracy:0.8832964897155762  train_auc_1:0.7038192749023438  val_loss:0.358445405960083  val_accuracy:0.8729282021522522  val_auc_1:0.6819758415222168 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 42.65it/s, epoch: 4/10 -  train_loss:0.31387007236480713  train_accuracy:0.88606196641922  train_auc_1:0.7519825100898743  val_loss:0.3427862823009491  val_accuracy:0.8729282021522522  val_auc_1:0.7419042587280273 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 45.85it/s, epoch: 5/10 -  train_loss:0.2894230782985687  train_accuracy:0.8866150379180908  train_auc_1:0.8085392713546753  val_loss:0.33072948455810547  val_accuracy:0.870718240737915  val_auc_1:0.7843313217163086 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 44.84it/s, epoch: 6/10 -  train_loss:0.27044418454170227  train_accuracy:0.8869742751121521  train_auc_1:0.8391960859298706  val_loss:0.3120502531528473  val_accuracy:0.8674033284187317  val_auc_1:0.8096477389335632 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 42.93it/s, epoch: 7/10 -  train_loss:0.25070708990097046  train_accuracy:0.8962942361831665  train_auc_1:0.8619815707206726  val_loss:0.31437328457832336  val_accuracy:0.8718231916427612  val_auc_1:0.838728666305542 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 43.73it/s, epoch: 8/10 -  train_loss:0.25882866978645325  train_accuracy:0.8933189511299133  train_auc_1:0.8460560441017151  val_loss:0.2909625768661499  val_accuracy:0.8773480653762817  val_auc_1:0.8433351516723633 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 45.62it/s, epoch: 9/10 -  train_loss:0.254334032535553  train_accuracy:0.8940818309783936  train_auc_1:0.8722440004348755  val_loss:0.2853069305419922  val_accuracy:0.8828729391098022  val_auc_1:0.8439790606498718 ]\n",
      "100%|██████████| 29/29 [00:00<00:00, 50.14it/s, epoch: 10/10 -  train_loss:0.24358023703098297  train_accuracy:0.8957411646842957  train_auc_1:0.8758358359336853  val_loss:0.2825777232646942  val_accuracy:0.8784530162811279  val_auc_1:0.8505613803863525 ]\n"
     ]
    }
   ],
   "source": [
    "history =  sl_model.fit(train_data,\n",
    "             train_label,\n",
    "             validation_data=(test_data,test_label),\n",
    "             epochs=10, \n",
    "             batch_size=train_batch_size,\n",
    "             shuffle=True,\n",
    "             verbose=1,\n",
    "             validation_freq=1,\n",
    "             dp_spent_step_freq=dp_spent_step_freq,)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "Let's visualize the training process"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:24.741564Z",
     "end_time": "2023-04-24T10:21:24.777702Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'train_loss': [0.4876196, 0.32520458, 0.33422568, 0.31387007, 0.28942308, 0.27044418, 0.2507071, 0.25882867, 0.25433403, 0.24358024], 'train_accuracy': [0.7790376, 0.8960129, 0.8832965, 0.88606197, 0.88661504, 0.8869743, 0.89629424, 0.89331895, 0.89408183, 0.89574116], 'train_auc_1': [0.52334833, 0.63739604, 0.7038193, 0.7519825, 0.8085393, 0.8391961, 0.8619816, 0.84605604, 0.872244, 0.87583584], 'val_loss': [0.38059726, 0.36565045, 0.3584454, 0.34278628, 0.33072948, 0.31205025, 0.31437328, 0.29096258, 0.28530693, 0.28257772], 'val_accuracy': [0.8729282, 0.8729282, 0.8729282, 0.8729282, 0.87071824, 0.8674033, 0.8718232, 0.87734807, 0.88287294, 0.878453], 'val_auc_1': [0.64764446, 0.6615355, 0.68197584, 0.74190426, 0.7843313, 0.80964774, 0.83872867, 0.84333515, 0.84397906, 0.8505614]}\n",
      "dict_keys(['train_loss', 'train_accuracy', 'train_auc_1', 'val_loss', 'val_accuracy', 'val_auc_1'])\n"
     ]
    }
   ],
   "source": [
    "print(history)\n",
    "print(history.keys())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:24.777702Z",
     "end_time": "2023-04-24T10:21:25.168441Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": "<Figure size 640x480 with 1 Axes>",
      "image/png": "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I80uzWkp/IhLu++++9i8eTMrVqwwuxSXdeDAAf75z3+yZMkSfHx8zC5HsP+joFu3bjz77LMAdOnShc2bNzN37lyFHxN89tlnfPjhh3z00Ue0b9+e9evXM27cOGJiYvT7uEAKP7UgPDwcd3d30tPTK+1PT08nKirKpKrk/vvvZ8GCBfz00080btzY7HJc1tq1a8nIyCA+Pr5in9Vq5aeffmL27NkUFxfj7u5uYoWuJzo6mnbt2lXa17ZtW7788kuTKnJtDzzwAJMnT+aWW24BoEOHDuzfv59p06Yp/FwgjfmpBV5eXnTt2pXExMSKfTabjcTERHr27GliZa7JMAzuv/9+vv76a3744QeaN29udkkurX///mzatIn169dXbN26dWPkyJGsX79ewccEvXr1OmX6hx07dtC0aVOTKnJtBQUFuLlV/rh2d3fHZrOZVJHzU8tPLZkwYQJ33HEH3bp1o0ePHsyaNYv8/HxGjx5tdmku57777uOjjz7iv//9L4GBgaSlpQEQHByMr6+vydW5nsDAwFPGW/n7+xMWFqZxWCYZP348l156Kc8++yw33XQTa9as4Y033uCNN94wuzSXNGzYMJ555hmaNGlC+/btWbduHS+++CJ33XWX2aU5LT3qXotmz57NjBkzSEtLo3Pnzrz88sskJCSYXZbLsVgsp90/b9487rzzztotRk6rT58+etTdZAsWLGDKlCns3LmT5s2bM2HCBP7617+aXZZLys3N5dFHH+Xrr78mIyODmJgYbr31VqZOnYqXl5fZ5TklhR8RERFxKRrzIyIiIi5F4UdERERcisKPiIiIuBSFHxEREXEpCj8iIiLiUhR+RERExKUo/IiIiIhLUfgRETkHFouF+fPnm12GiFQDhR8RqfPuvPNOLBbLKdvgwYPNLk1EnJDW9hIRpzB48GDmzZtXaZ+3t7dJ1YiIM1PLj4g4BW9vb6KioiptoaGhgL1L6rXXXmPIkCH4+vrSokULvvjii0rnb9q0iX79+uHr60tYWBh33303eXl5lY55++23ad++Pd7e3kRHR3P//fdXev/o0aNcd911+Pn50bp1a7755puavWkRqREKPyJSLzz66KOMGDGCDRs2MHLkSG655Ra2bdsGQH5+PoMGDSI0NJTffvuNzz//nKVLl1YKN6+99hr33Xcfd999N5s2beKbb76hVatWlX7GE088wU033cTGjRu56qqrGDlyJMePH6/V+xSRamCIiNRxd9xxh+Hu7m74+/tX2p555hnDMAwDMP7+979XOichIcG45557DMMwjDfeeMMIDQ018vLyKt7/9ttvDTc3NyMtLc0wDMOIiYkxHn744SprAIxHHnmk4nVeXp4BGAsXLqy2+xSR2qExPyLiFPr27ctrr71WaV+DBg0qvu/Zs2el93r27Mn69esB2LZtG506dcLf37/i/V69emGz2di+fTsWi4VDhw7Rv3//M9bQsWPHiu/9/f0JCgoiIyPjQm9JREyi8CMiTsHf3/+Ubqjq4uvre07HeXp6VnptsViw2Ww1UZKI1CCN+RGRemHVqlWnvG7bti0Abdu2ZcOGDeTn51e8/8svv+Dm5kabNm0IDAykWbNmJCYm1mrNImIOtfyIiFMoLi4mLS2t0j4PDw/Cw8MB+Pzzz+nWrRuXXXYZH374IWvWrOGtt94CYOTIkTz22GPccccdPP744xw5coSxY8fyl7/8hcjISAAef/xx/v73vxMREcGQIUPIzc3ll19+YezYsbV7oyJS4xR+RMQpLFq0iOjo6Er72rRpQ3JyMmB/EuuTTz7h3nvvJTo6mo8//ph27doB4Ofnx+LFi/nnP/9J9+7d8fPzY8SIEbz44osV17rjjjsoKiripZdeYtKkSYSHh3PDDTfU3g2KSK2xGIZhmF2EiIgjLBYLX3/9NcOHDze7FBFxAhrzIyIiIi5F4UdERERcisb8iIjTU++9iJwPtfyIiIiIS1H4EREREZei8CMiIiIuReFHREREXIrCj4iIiLgUhR8RERFxKQo/IiIi4lIUfkRERMSlKPyIiIiIS/l/KWHnbVhG+YQAAAAASUVORK5CYII="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the change of loss during training\n",
    "plt.plot(history['train_loss'])\n",
    "plt.plot(history['val_loss'])\n",
    "plt.title('Model loss')\n",
    "plt.ylabel('Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.legend(['Train','Val'], loc='upper right')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:25.164939Z",
     "end_time": "2023-04-24T10:21:25.383950Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": "<Figure size 640x480 with 1 Axes>",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHHCAYAAABXx+fLAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABerklEQVR4nO3deVzUdf4H8Nd3BhhmuORGFDnU8AiPRMkjuyiPZLO1LLU8Mt3Km+q33pqu0rXEpqa5q9auR66m5WZZRoeamgZpmregKMrlwc0wzHx/f3yZgRFQBge+M8zr+Xh8H8B3vvOd98Bu8/JzCqIoiiAiIiJyIAq5CyAiIiJqagxARERE5HAYgIiIiMjhMAARERGRw2EAIiIiIofDAEREREQOhwGIiIiIHA4DEBERETkcBiAiIiJyOAxARNSkBEHAwoULLX7ehQsXIAgCPv74Y6vXRESOhwGIyAF9/PHHEAQBgiBg3759NR4XRREhISEQBAFDhgyRoUIiosbFAETkwFxdXbFx48Ya53/66SdcvnwZKpVKhqqIiBofAxCRAxs8eDC2bNmCiooKs/MbN25Ejx49EBQUJFNljqO4uFjuEogcEgMQkQMbMWIErl27ht27d5vOlZeXY+vWrRg5cmStzykuLsZrr72GkJAQqFQqREZG4r333oMoimbXabVazJgxA/7+/vDw8MCf/vQnXL58udZ7ZmZm4sUXX0RgYCBUKhU6d+6MtWvXNug9Xb9+Ha+//jqioqLg7u4OT09PDBo0CEePHq1xbVlZGRYuXIh77rkHrq6uaNmyJf785z/j/PnzpmsMBgP+8Y9/ICoqCq6urvD398fAgQPx66+/Arj92KRbxzstXLgQgiDgxIkTGDlyJLy9vdGvXz8AwO+//46xY8ciIiICrq6uCAoKwosvvohr167V+vsaP348goODoVKpEB4ejldeeQXl5eVIS0uDIAh4//33azxv//79EAQBmzZtsvTXStTsOMldABHJJywsDL1798amTZswaNAgAMDXX3+N/Px8PPfcc/jggw/MrhdFEX/605/www8/YPz48ejWrRu++eYbvPHGG8jMzDT70H3ppZewfv16jBw5En369MH333+PJ554okYN2dnZuP/++yEIAiZPngx/f398/fXXGD9+PAoKCjB9+nSL3lNaWho+//xzPPPMMwgPD0d2djY++ugjPPjggzhx4gSCg4MBAHq9HkOGDEFycjKee+45TJs2DYWFhdi9ezeOHz+Otm3bAgDGjx+Pjz/+GIMGDcJLL72EiooK7N27FwcPHkR0dLRFtRk988wzaN++PZYuXWoKjrt370ZaWhrGjRuHoKAg/PHHH1i9ejX++OMPHDx4EIIgAACuXLmCXr164ebNm5g4cSI6dOiAzMxMbN26FSUlJYiIiEDfvn2xYcMGzJgxw+x1N2zYAA8PDzz55JMNqpuoWRGJyOGsW7dOBCAePnxYXL58uejh4SGWlJSIoiiKzzzzjPjwww+LoiiKoaGh4hNPPGF63ueffy4CEP/2t7+Z3e/pp58WBUEQz507J4qiKB45ckQEIL766qtm140cOVIEIC5YsMB0bvz48WLLli3FvLw8s2ufe+450cvLy1RXenq6CEBct27dbd9bWVmZqNfrzc6lp6eLKpVKXLRokenc2rVrRQBiYmJijXsYDAZRFEXx+++/FwGIU6dOrfOa29V163tdsGCBCEAcMWJEjWuN77O6TZs2iQDEPXv2mM6NHj1aVCgU4uHDh+us6aOPPhIBiCdPnjQ9Vl5eLvr5+Yljxoyp8TwiR8QuMCIHN3z4cJSWluLLL79EYWEhvvzyyzq7v7766isolUpMnTrV7Pxrr70GURTx9ddfm64DUOO6W1tzRFHEZ599hri4OIiiiLy8PNMxYMAA5OfnIzU11aL3o1KpoFBI/2nT6/W4du0a3N3dERkZaXavzz77DH5+fpgyZUqNexhbWz777DMIgoAFCxbUeU1DvPzyyzXOqdVq0/dlZWXIy8vD/fffDwCmug0GAz7//HPExcXV2vpkrGn48OFwdXXFhg0bTI998803yMvLw/PPP9/guomaEwYgIgfn7++P2NhYbNy4Edu2bYNer8fTTz9d67UXL15EcHAwPDw8zM537NjR9Ljxq0KhMHUjGUVGRpr9nJubi5s3b2L16tXw9/c3O8aNGwcAyMnJsej9GAwGvP/++2jfvj1UKhX8/Pzg7++P33//Hfn5+abrzp8/j8jISDg51T0S4Pz58wgODoaPj49FNdxJeHh4jXPXr1/HtGnTEBgYCLVaDX9/f9N1xrpzc3NRUFCAe++997b3b9GiBeLi4sxm+G3YsAGtWrXCI488YsV3QmS/OAaIiDBy5EhMmDABWVlZGDRoEFq0aNEkr2swGAAAzz//PMaMGVPrNV26dLHonkuXLsW8efPw4osvYvHixfDx8YFCocD06dNNr2dNdbUE6fX6Op9TvbXHaPjw4di/fz/eeOMNdOvWDe7u7jAYDBg4cGCD6h49ejS2bNmC/fv3IyoqCjt27MCrr75qah0jcnQMQESEp556Cn/5y19w8OBBbN68uc7rQkND8d1336GwsNCsFejUqVOmx41fDQaDqZXF6PTp02b3M84Q0+v1iI2Ntcp72bp1Kx5++GGsWbPG7PzNmzfh5+dn+rlt27b45ZdfoNPp4OzsXOu92rZti2+++QbXr1+vsxXI29vbdP/qjK1h9XHjxg0kJyfjzTffxPz5803nz549a3adv78/PD09cfz48Tvec+DAgfD398eGDRsQExODkpISvPDCC/Wuiai54z8FiAju7u5YuXIlFi5ciLi4uDqvGzx4MPR6PZYvX252/v3334cgCKaZZMavt84iS0pKMvtZqVRi2LBh+Oyzz2r9UM/NzbX4vSiVyhpT8rds2YLMzEyzc8OGDUNeXl6N9wLA9Pxhw4ZBFEW8+eabdV7j6ekJPz8/7Nmzx+zxDz/80KKaq9/T6Nbfl0KhwNChQ/G///3PNA2/tpoAwMnJCSNGjMB///tffPzxx4iKirK4NY2oOWMLEBEBQJ1dUNXFxcXh4Ycfxpw5c3DhwgV07doV3377Lb744gtMnz7dNOanW7duGDFiBD788EPk5+ejT58+SE5Oxrlz52rc86233sIPP/yAmJgYTJgwAZ06dcL169eRmpqK7777DtevX7fofQwZMgSLFi3CuHHj0KdPHxw7dgwbNmxARESE2XWjR4/Gv//9b8THx+PQoUN44IEHUFxcjO+++w6vvvoqnnzySTz88MN44YUX8MEHH+Ds2bOm7qi9e/fi4YcfxuTJkwFIU/7feustvPTSS4iOjsaePXtw5syZetfs6emJ/v3745133oFOp0OrVq3w7bffIj09vca1S5cuxbfffosHH3wQEydORMeOHXH16lVs2bIF+/btM+u+HD16ND744AP88MMPePvtty36PRI1e7LNPyMi2VSfBn87t06DF0VRLCwsFGfMmCEGBweLzs7OYvv27cV3333XNAXbqLS0VJw6daro6+srurm5iXFxceKlS5dqTA0XRVHMzs4WJ02aJIaEhIjOzs5iUFCQ+Oijj4qrV682XWPJNPjXXntNbNmypahWq8W+ffuKBw4cEB988EHxwQcfNLu2pKREnDNnjhgeHm563aefflo8f/686ZqKigrx3XffFTt06CC6uLiI/v7+4qBBg8SUlBSz+4wfP1708vISPTw8xOHDh4s5OTl1ToPPzc2tUffly5fFp556SmzRooXo5eUlPvPMM+KVK1dq/X1dvHhRHD16tOjv7y+qVCoxIiJCnDRpkqjVamvct3PnzqJCoRAvX758298bkaMRRPGWNlciImo2unfvDh8fHyQnJ8tdCpFN4RggIqJm6tdff8WRI0cwevRouUshsjlsASIiamaOHz+OlJQU/P3vf0deXh7S0tLg6uoqd1lENoUtQEREzczWrVsxbtw46HQ6bNq0ieGHqBZsASIiIiKHwxYgIiIicjgMQERERORwuBBiLQwGA65cuQIPD4+72vGZiIiImo4oiigsLERwcPAd971jAKrFlStXEBISIncZRERE1ACXLl1C69atb3sNA1AtjJs8Xrp0CZ6enjJXQ0RERPVRUFCAkJAQs82a62ITAWjFihV49913kZWVha5du2LZsmXo1atXrdfqdDokJCTgk08+QWZmJiIjI/H2229j4MCBDb7nrYzdXp6engxAREREdqY+w1dkHwS9efNmxMfHY8GCBUhNTUXXrl0xYMAA5OTk1Hr93Llz8dFHH2HZsmU4ceIEXn75ZTz11FP47bffGnxPIiIiciyyrwMUExODnj17Yvny5QCkAcghISGYMmUKZs6cWeP64OBgzJkzB5MmTTKdGzZsGNRqNdavX9+ge96qoKAAXl5eyM/PZwsQERGRnbDk81vWFqDy8nKkpKQgNjbWdE6hUCA2NhYHDhyo9TlarbbGqqZqtRr79u27q3sWFBSYHURERNR8yToGKC8vD3q9HoGBgWbnAwMDcerUqVqfM2DAACQmJqJ///5o27YtkpOTsW3bNuj1+gbfMyEhAW+++abF9ev1euh0OoufRxJnZ2colUq5yyAiIgdkE4OgLfGPf/wDEyZMQIcOHSAIAtq2bYtx48Zh7dq1Db7nrFmzEB8fb/rZOIq8LqIoIisrCzdv3mzwa5KkRYsWCAoK4npLRETUpGQNQH5+flAqlcjOzjY7n52djaCgoFqf4+/vj88//xxlZWW4du0agoODMXPmTERERDT4niqVCiqVqt51G8NPQEAA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iwt69OiB5ORk0zmDwYDk5GT07t37ts/dsmULtFotnn/+ebPzOp0OOp0OCoX5W1MqlTAYDNYrvgHyS3VwVzlx/A8REZHMZG0BAqQp62PGjEF0dDR69eqFpKQkFBcXY9y4cQCA0aNHo1WrVkhISDB73po1azB06FD4+vqanff09MSDDz6IN954A2q1GqGhofjpp5/w73//G4mJiU32vmrzVPfWGNqtFcp08gYxIiIiRyd7AHr22WeRm5uL+fPnIysrC926dcOuXbtMA6MzMjJqtOacPn0a+/btw7ffflvrPT/99FPMmjULo0aNwvXr1xEaGoolS5bg5ZdfbvT3cyeCIEDtopS7DCIiIocmiKIoyl2ErSkoKICXlxfy8/Ph6ekpdzlERERUD5Z8ftv1LDAiIiKihmAAIiIiIofDAEREREQOhwGIiIiIHA4DEBERETkcBiAiIiJyOAxARERE5HAYgIiIiMjhMAARERGRw2EAIiIiIofDAEREREQOhwGIiIiIHI7su8HbIuP+sAUFBTJXQkRERPVl/Nyuzz7vDEC1KCwsBACEhITIXAkRERFZqrCwEF5eXre9RhDrE5McjMFgwJUrV+Dh4QFBEKx674KCAoSEhODSpUvw9PS06r3Jcvx72Bb+PWwL/x62h3+T2xNFEYWFhQgODoZCcftRPmwBqoVCoUDr1q0b9TU8PT35P14bwr+HbeHfw7bw72F7+Dep251afow4CJqIiIgcDgMQERERORwGoCamUqmwYMECqFQquUsh8O9ha/j3sC38e9ge/k2sh4OgiYiIyOGwBYiIiIgcDgMQERERORwGICIiInI4DEBERETkcBiAmtCKFSsQFhYGV1dXxMTE4NChQ3KX5LASEhLQs2dPeHh4ICAgAEOHDsXp06flLosAvPXWWxAEAdOnT5e7FIeWmZmJ559/Hr6+vlCr1YiKisKvv/4qd1kOSa/XY968eQgPD4darUbbtm2xePHieu13RXVjAGoimzdvRnx8PBYsWIDU1FR07doVAwYMQE5OjtylOaSffvoJkyZNwsGDB7F7927odDo8/vjjKC4ulrs0h3b48GF89NFH6NKli9ylOLQbN26gb9++cHZ2xtdff40TJ07g73//O7y9veUuzSG9/fbbWLlyJZYvX46TJ0/i7bffxjvvvINly5bJXZpd4zT4JhITE4OePXti+fLlAKT9xkJCQjBlyhTMnDlT5uooNzcXAQEB+Omnn9C/f3+5y3FIRUVFuO+++/Dhhx/ib3/7G7p164akpCS5y3JIM2fOxM8//4y9e/fKXQoBGDJkCAIDA7FmzRrTuWHDhkGtVmP9+vUyVmbf2ALUBMrLy5GSkoLY2FjTOYVCgdjYWBw4cEDGysgoPz8fAODj4yNzJY5r0qRJeOKJJ8z+f0Ly2LFjB6Kjo/HMM88gICAA3bt3xz//+U+5y3JYffr0QXJyMs6cOQMAOHr0KPbt24dBgwbJXJl942aoTSAvLw96vR6BgYFm5wMDA3Hq1CmZqiIjg8GA6dOno2/fvrj33nvlLschffrpp0hNTcXhw4flLoUApKWlYeXKlYiPj8fs2bNx+PBhTJ06FS4uLhgzZozc5TmcmTNnoqCgAB06dIBSqYRer8eSJUswatQouUuzawxA5PAmTZqE48ePY9++fXKX4pAuXbqEadOmYffu3XB1dZW7HIL0j4Lo6GgsXboUANC9e3ccP34cq1atYgCSwX//+19s2LABGzduROfOnXHkyBFMnz4dwcHB/HvcBQagJuDn5welUons7Gyz89nZ2QgKCpKpKgKAyZMn48svv8SePXvQunVructxSCkpKcjJycF9991nOqfX67Fnzx4sX74cWq0WSqVSxgodT8uWLdGpUyezcx07dsRnn30mU0WO7Y033sDMmTPx3HPPAQCioqJw8eJFJCQkMADdBY4BagIuLi7o0aMHkpOTTecMBgOSk5PRu3dvGStzXKIoYvLkydi+fTu+//57hIeHy12Sw3r00Udx7NgxHDlyxHRER0dj1KhROHLkCMOPDPr27VtjWYgzZ84gNDRUpoocW0lJCRQK849rpVIJg8EgU0XNA1uAmkh8fDzGjBmD6Oho9OrVC0lJSSguLsa4cePkLs0hTZo0CRs3bsQXX3wBDw8PZGVlAQC8vLygVqtlrs6xeHh41Bh75ebmBl9fX47JksmMGTPQp08fLF26FMOHD8ehQ4ewevVqrF69Wu7SHFJcXByWLFmCNm3aoHPnzvjtt9+QmJiIF198Ue7S7BqnwTeh5cuX491330VWVha6deuGDz74ADExMXKX5ZAEQaj1/Lp16zB27NimLYZqeOihhzgNXmZffvklZs2ahbNnzyI8PBzx8fGYMGGC3GU5pMLCQsybNw/bt29HTk4OgoODMWLECMyfPx8uLi5yl2e3GICIiIjI4XAMEBERETkcBiAiIiJyOAxARERE5HAYgIiIiMjhMAARERGRw2EAIiIiIofDAEREREQOhwGIiKgeBEHA559/LncZRGQlDEBEZPPGjh0LQRBqHAMHDpS7NCKyU9wLjIjswsCBA7Fu3TqzcyqVSqZqiMjesQWIiOyCSqVCUFCQ2eHt7Q1A6p5auXIlBg0aBLVajYiICGzdutXs+ceOHcMjjzwCtVoNX19fTJw4EUVFRWbXrF27Fp07d4ZKpULLli0xefJks8fz8vLw1FNPQaPRoH379tixY0fjvmkiajQMQETULMybNw/Dhg3D0aNHMWrUKDz33HM4efIkAKC4uBgDBgyAt7c3Dh8+jC1btuC7774zCzgrV67EpEmTMHHiRBw7dgw7duxAu3btzF7jzTffxPDhw/H7779j8ODBGDVqFK5fv96k75OIrEQkIrJxY8aMEZVKpejm5mZ2LFmyRBRFUQQgvvzyy2bPiYmJEV955RVRFEVx9erVore3t1hUVGR6fOfOnaJCoRCzsrJEURTF4OBgcc6cOXXWAECcO3eu6eeioiIRgPj1119b7X0SUdPhGCAisgsPP/wwVq5caXbOx8fH9H3v3r3NHuvduzeOHDkCADh58iS6du0KNzc30+N9+/aFwWDA6dOnIQgCrly5gkcfffS2NXTp0sX0vZubGzw9PZGTk9PQt0REMmIAIiK74ObmVqNLylrUanW9rnN2djb7WRAEGAyGxiiJiBoZxwARUbNw8ODBGj937NgRANCxY0ccPXoUxcXFpsd//vlnKBQKREZGwsPDA2FhYUhOTm7SmolIPmwBIiK7oNVqkZWVZXbOyckJfn5+AIAtW7YgOjoa/fr1w4YNG3Do0CGsWbMGADBq1CgsWLAAY8aMwcKFC5Gbm4spU6bghRdeQGBgIABg4cKFePnllxEQEIBBgwahsLAQP//8M6ZMmdK0b5SImgQDEBHZhV27dqFly5Zm5yIjI3Hq1CkA0gytTz/9FK+++ipatmyJTZs2oVOnTgAAjUaDb775BtOmTUPPnj2h0WgwbNgwJCYmmu41ZswYlJWV4f3338frr78OPz8/PP300033BomoSQmiKIpyF0FEdDcEQcD27dsxdOhQuUshIjvBMUBERETkcBiAiIiIyOFwDBAR2T325BORpdgCRERERA6HAYiIiIgcDgMQERERORwGICIiInI4DEBERETkcBiAiIiIyOEwABEREZHDYQAiIiIih8MARERERA7n/wHbSMRtQwtipwAAAABJRU5ErkJggg=="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the change of accuracy during training\n",
    "plt.plot(history['train_accuracy'])\n",
    "plt.plot(history['val_accuracy'])\n",
    "plt.title('Model accuracy')\n",
    "plt.ylabel('Accuracy')\n",
    "plt.xlabel('Epoch')\n",
    "plt.legend(['Train', 'Val'], loc='upper left')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:25.384951Z",
     "end_time": "2023-04-24T10:21:25.629947Z"
    },
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": "<Figure size 640x480 with 1 Axes>",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHHCAYAAABXx+fLAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABx4klEQVR4nO3dd3gU5frG8e+mF0ioCSQEQpcOBoh00HgAFUVFekcQBCyoP+EoKDY8Fg4HUZo0pYOo2FCJgNKRjnRCh4SeBmm78/tjYSEQIBuSbJK9P9eVy8zs7OyzJLI3M+/7PibDMAxEREREnIiLowsQERERyW0KQCIiIuJ0FIBERETE6SgAiYiIiNNRABIRERGnowAkIiIiTkcBSERERJyOApCIiIg4HQUgERERcToKQCIFmMlk4u2337b7eUeOHMFkMjFz5sxsr8mZ6M9RJO9SABLJYTNnzsRkMmEymVi9evUtjxuGQUhICCaTiccee8wBFWaPn3/+GZPJRFBQEBaLxdHlZCg0NPS2f8Z///13gQgrcXFxjB49mjp16lCoUCG8vb2pWbMmr7/+OqdOnXJ0eSJ5hgKQSC7x8vJi7ty5t+xftWoVJ06cwNPT0wFVZZ85c+YQGhrK6dOn+eOPPxxdjlOKioqibt26vPvuu1SvXp3//Oc/jB8/nlatWjFt2jRatmzp6BJF8gwFIJFc8sgjj7Bo0SLS0tLS7Z87dy5hYWGUKlXKQZXdu8TERL7//nuGDRtGvXr1mDNnTqaeZ7FYSEpKyuHqCo7ExMTbPpaWlsZTTz1FTEwMK1euZN68eQwePJj+/fvz2WefERUVxTPPPJMtdSQlJeXZq3wimaUAJJJLunTpwvnz5/n9999t+1JSUli8eDFdu3bN8DmJiYm88sorhISE4OnpSdWqVfnkk08wDCPdccnJybz88suULFmSwoUL8/jjj3PixIkMz3ny5En69u1LYGAgnp6e1KhRg+nTp9/Te/v222+5cuUKzzzzDJ07d2bJkiUZBhuTycSQIUOYM2cONWrUwNPTk2XLlmW6rpSUFEaNGkVYWBj+/v74+vrSrFkzVqxYcU/1307v3r0pVKgQJ0+epH379hQqVIiSJUvy6quvYjab0x176dIlevfujb+/P0WKFKFXr15cunQpw/Pu3buXDh06UKxYMby8vKhfvz5Lly5Nd8y1W6erVq3i+eefJyAggDJlyty21m+++Ybt27fzxhtv0LRp01se9/Pz4/3337dth4aG0rt371uOa9myZborRStXrsRkMjF//nzefPNNgoOD8fHxYcuWLZhMJmbNmnXLOX799VdMJhM//vijbV9O/N6J3As3Rxcg4ixCQ0Np1KgR8+bNo23btgD88ssvxMbG0rlzZ8aPH5/ueMMwePzxx1mxYgX9+vWjbt26/Prrr7z22mucPHmS//73v7Zjn332WWbPnk3Xrl1p3Lgxf/zxB48++ugtNcTExPDAAw/YgkjJkiX55Zdf6NevH3Fxcbz00ktZem9z5syhVatWlCpVis6dOzN8+HB++OGHDK84/PHHHyxcuJAhQ4ZQokQJQkNDM11XXFwcX375JV26dKF///7Ex8czbdo0WrduzcaNG6lbt26W6r8Ts9lM69atCQ8P55NPPmH58uV8+umnVKxYkUGDBgHWn9UTTzzB6tWrGThwINWqVePbb7+lV69et5zvn3/+oUmTJgQHBzN8+HB8fX1ZuHAh7du355tvvuHJJ59Md/zzzz9PyZIlGTVq1B2vAF0LUD169MjGd3/du+++i4eHB6+++irJyclUr16dChUqsHDhwlve54IFCyhatCitW7cGcu73TuSeGCKSo2bMmGEAxqZNm4wJEyYYhQsXNi5fvmwYhmE888wzRqtWrQzDMIxy5coZjz76qO153333nQEY7733XrrzdejQwTCZTMbBgwcNwzCMbdu2GYDx/PPPpzuua9euBmC89dZbtn39+vUzSpcubZw7dy7dsZ07dzb8/f1tdR0+fNgAjBkzZtz1/cXExBhubm7G1KlTbfsaN25sPPHEE7ccCxguLi7GP//8k25/ZutKS0szkpOT0x1z8eJFIzAw0Ojbt+9da735z/hGmzZtuuU99+rVywCMd955J92x9erVM8LCwmzb135WH330kW1fWlqa0axZs1vO+dBDDxm1atUykpKSbPssFovRuHFjo3LlyrZ9135vmjZtaqSlpd31vdWrV8/w9/e/63HXlCtXzujVq9ct+1u0aGG0aNHCtr1ixQoDMCpUqGD7OVwzYsQIw93d3bhw4YJtX3JyslGkSJF0P4/M/nxFcpNugYnkoo4dO3LlyhV+/PFH4uPj+fHHH297++vnn3/G1dWVF154Id3+V155BcMw+OWXX2zHAbccd/O/qg3D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nk/kl52nARjQQm0vRETEeTnsCpCHhwdhYWFERkba9lksFiIjI2nUqFGGz2nSpAkHDx7EYrHY9u3fv5/SpUvj4eGRpXM6ky//OozFgJZVS3JfqYI3uFtERCSzHHoLbNiwYUydOpVZs2axZ88eBg0aRGJiIn369AGgZ8+ejBgxwnb8oEGDuHDhAi+++CL79+/np59+4oMPPmDw4MGZPqezOp+QzMK/rbf2nmte0cHViIiIOJbDboEBdOrUibNnzzJq1Ciio6OpW7cuy5Ytsw1iPnbsGC4u1zNaSEgIv/76Ky+//DK1a9cmODiYF198kddffz3T53RWs9YdJTnNQp0y/jxQQU1PRUTEuTl0HaC8qqCtA3Q5JY3GH/7BpcupfNHtfh6pVdrRJYmIiGS7fLEOkOSehZuOc+lyKuWK+9C6hpqeioiIKAAVcGlmC1P/UtNTERGRGykAFXA/7bQ2PS3u60GHsDKOLkdERCRPUAAqwAzDYPIq68KHvRuHqumpiIjIVQpABdjqg+fYfToOb3dXejQq5+hyRERE8gwFoALs2tWfzg1DKOLj4eBqRERE8g4FoAJq18lYVh88h6uLiX5qeioiIpKOAlABda3pabvapSlT1MfB1YiIiOQtCkAF0PELl/lpxykABqjthYiIyC0UgAqgL/+KwmJA8yolqR6U/1eyFhERyW4KQAXMhcQUFlxtejqweQUHVyMiIpI3KQAVMF+tO0JSqoVawf40qljc0eWIiIjkSQpABciVFDOz1h4B4LkWFTCZ1PZCREQkIwpABciizce5eDmVssV8aKOmpyIiIrelAFRAWJueWqe+929WHjdX/WhFRERuR5+SBcQvu6I5fuEKxXw96BAW4uhyRERE8jQFoALAMAwm/3kIgF6NQvH2UNNTERGRO1EAKgDWHjrPrpPWpqc91fRURETkrhSACoBJq6xXfzo1CKGor5qeioiI3I0CUD73z6lY/jqgpqciIiL2UADK56ZcbXr6aK3ShBRT01MREZHMUADKx45fuMyPO04DMEBtL0RERDJNASgfm7b6MGaLQbPKJagZ7O/ockRERPINBaB86mJiCgs2WZuePte8ooOrERERyV8UgPKp2euPciXVTI0gP5pUUtNTEREReygA5UNJqWZm2pqeVlTTUxERETspAOVDizef4HxiCmWKevNITTU9FRERsZcCUD5jthi2pqfPNlXTUxERkazQp2c+8+s/0Rw9f5kiPu50bKCmpyIiIlmhAJSPGIbB5KttL3o2CsXHw83BFYmIiORPCkD5yPqoC2w/EYunmwu91PRUREQkyxSA8pHJf1qv/nSsH0LxQp4OrkZERCT/UgDKJ/acjmPlvrO4mODZZmp6KiIici8UgPKJqVebnratVZpyxX0dXI2IiEj+pgCUD5y8dIWl208B8JyanoqIiNwzBaB8YPrqw6RZDBpXLE7tMkUcXY6IiEi+lycC0Oeff05oaCheXl6Eh4ezcePG2x47c+ZMTCZTui8vL690x/Tu3fuWY9q0aZPTbyNHxF5OZd7GY4C17YWIiIjcO4cvJLNgwQKGDRvGpEmTCA8PZ9y4cbRu3Zp9+/YREBCQ4XP8/PzYt2+fbTujXlht2rRhxowZtm1Pz/w5a2r2hqNcTjFzX6nCNK9cwtHliIiIFAgOvwI0duxY+vfvT58+fahevTqTJk3Cx8eH6dOn3/Y5JpOJUqVK2b4CAwNvOcbT0zPdMUWLFs3Jt5EjklLNzFhzGICBanoqIiKSbRwagFJSUti8eTMRERG2fS4uLkRERLBu3brbPi8hIYFy5coREhLCE088wT///HPLMStXriQgIICqVasyaNAgzp8/nyPvISct2XKScwkpBBfx5tHapR1djoiISIHh0AB07tw5zGbzLVdwAgMDiY6OzvA5VatWZfr06Xz//ffMnj0bi8VC48aNOXHihO2YNm3a8NVXXxEZGcl//vMfVq1aRdu2bTGbzRmeMzk5mbi4uHRfjnZj09N+TcvjrqanIiIi2cbhY4Ds1ahRIxo1amTbbty4MdWqVWPy5Mm8++67AHTu3Nn2eK1atahduzYVK1Zk5cqVPPTQQ7ecc8yYMYwePTrni7fD77ujOXwuEX9vdzqp6amIiEi2cuhlhRIlSuDq6kpMTEy6/TExMZQqVSpT53B3d6devXocPHjwtsdUqFCBEiVK3PaYESNGEBsba/s6fvx45t9EDjAMg4mrrFd/ejYqh69nvsupIiIieZpDA5CHhwdhYWFERkba9lksFiIjI9Nd5bkTs9nMzp07KV369mNkTpw4wfnz5297jKenJ35+fum+HGnj4QtsP34JDzcXejUOdWgtIiIiBZHDB5YMGzaMqVOnMmvWLPbs2cOgQYNITEykT58+APTs2ZMRI0bYjn/nnXf47bffiIqKYsuWLXTv3p2jR4/y7LPPAtYB0q+99hrr16/nyJEjREZG8sQTT1CpUiVat27tkPdor8lX2148E1aGEmp6KiIiku0cfm+lU6dOnD17llGjRhEdHU3dunVZtmyZbWD0sWPHcHG5ntMuXrxI//79iY6OpmjRooSFhbF27VqqV68OgKurKzt27GDWrFlcunSJoKAg/vWvf/Huu+/mi7WA9kXH88feM5hM0L+Z2l6IiIjkBJNhGIaji8hr4uLi8Pf3JzY2Ntdvh72ycDvfbDnBI7VK8UW3sFx9bRERkfzMns9vh98Ck+tOx17h+20nAXiuudpeiIiI5BQFoDzkWtPTByoUo05IEUeXIyIiUmApAOURsVdSmbtBTU9FRERygwJQHjFnw1ESU8xUDSxMyyolHV2OiIhIgaYAlAdYm54eAeC5FhXU9FRERCSHKQDlAd9tPcnZ+GSC/L1oVyfI0eWIiIgUeApADmaxGEy5uvBhXzU9FRERyRX6tHWw3/fEEHUuET8vNzo3LOvockRERJyCApADGYbBpFWHAOjRqByF1PRUREQkVygAOdDfRy+y9ZianoqIiOQ2BSAHmnz16s/T95choLCXg6sRERFxHgpADnIgJp7le641PS3v6HJEREScigKQg1yb+dW6eikqlCzk4GpERESciwKQA0THJvHdtaanLSo4uBoRERHnowDkADPWHibVbNCwfDHqlS3q6HJEREScjgJQLotLSmXuemvT04G6+iMiIuIQCkC5bN6GY8Qnp1ElsBAtqwQ4uhwRERGnpACUi5LTzExfcxiAAc0r4uKipqciIiKOoACUi77fdoqYuGRK+XnxuJqeioiIOIwCUC66kJiCl7sL/ZqWx8NNf/QiIiKOouZTuWhgi4p0rB+Cp8KPiIiIQykA5bJivh6OLkFERMTp6VKEiIiIOB0FIBEREXE6CkAiIiLidBSARERExOkoAImIiIjTUQASERERp6MAJCIiIk5HAUhEREScjgKQiIiIOB0FIBEREXE6CkAiIiLidBSARERExOkoAImIiIjTUTf4DBiGAUBcXJyDKxEREZHMuva5fe1z/E4UgDIQHx8PQEhIiIMrEREREXvFx8fj7+9/x2NMRmZikpOxWCycOnWKwoULYzKZsvXccXFxhISEcPz4cfz8/LL13GI//TzyFv088hb9PPIW/TzuzjAM4uPjCQoKwsXlzqN8dAUoAy4uLpQpUyZHX8PPz0+/wHmIfh55i34eeYt+HnmLfh53drcrP9doELSIiIg4HQUgERERcToKQLnM09OTt956C09PT0eXIujnkdfo55G36OeRt+jnkb00CFpEREScjq4AiYiIiNNRABIRERGnowAkIiIiTkcBSERERJyOAlAu+vzzzwkNDcXLy4vw8HA2btzo6JKc0pgxY2jQoAGFCxcmICCA9u3bs2/fPkeXJVd9+OGHmEwmXnrpJUeX4tROnjxJ9+7dKV68ON7e3tSqVYu///7b0WU5JbPZzMiRIylfvjze3t5UrFiRd999N1P9ruT2FIByyYIFCxg2bBhvvfUWW7ZsoU6dOrRu3ZozZ844ujSns2rVKgYPHsz69ev5/fffSU1N5V//+heJiYmOLs3pbdq0icmTJ1O7dm1Hl+LULl68SJMmTXB3d+eXX35h9+7dfPrppxQtWtTRpTml//znP0ycOJEJEyawZ88e/vOf//DRRx/x2WefObq0fE3T4HNJeHg4DRo0YMKECYC131hISAhDhw5l+PDhDq7OuZ09e5aAgABWrVpF8+bNHV2O00pISOD+++/niy++4L333qNu3bqMGzfO0WU5peHDh7NmzRr++usvR5ciwGOPPUZgYCDTpk2z7Xv66afx9vZm9uzZDqwsf9MVoFyQkpLC5s2biYiIsO1zcXEhIiKCdevWObAyAYiNjQWgWLFiDq7EuQ0ePJhHH3003f8n4hhLly6lfv36PPPMMwQEBFCvXj2mTp3q6LKcVuPGjYmMjGT//v0AbN++ndWrV9O2bVsHV5a/qRlqLjh37hxms5nAwMB0+wMDA9m7d6+DqhKwXol76aWXaNKkCTVr1nR0OU5r/vz5bNmyhU2bNjm6FAGioqKYOHEiw4YN49///jebNm3ihRdewMPDg169ejm6PKczfPhw4uLiuO+++3B1dcVsNvP+++/TrVs3R5eWrykAiVMbPHgwu3btYvXq1Y4uxWkdP36cF198kd9//x0vLy9HlyNY/2FQv359PvjgAwDq1avHrl27mDRpkgKQAyxcuJA5c+Ywd+5catSowbZt23jppZcICgrSz+MeKADlghIlSuDq6kpMTEy6/TExMZQqVcpBVcmQIUP48ccf+fPPPylTpoyjy3Famzdv5syZM9x///22fWazmT///JMJEyaQnJyMq6urAyt0PqVLl6Z69erp9lWrVo1vvvnGQRU5t9dee43hw4fTuXNnAGrVqsXRo0cZM2aMAtA90BigXODh4UFYWBiRkZG2fRaLhcjISBo1auTAypyTYRgMGTKEb7/9lj/++IPy5cs7uiSn9tBDD7Fz5062bdtm+6pfvz7dunVj27ZtCj8O0KRJk1uWhti/fz/lypVzUEXO7fLly7i4pP+4dnV1xWKxOKiigkFXgHLJsGHD6NWrF/Xr16dhw4aMGzeOxMRE+vTp4+jSnM7gwYOZO3cu33//PYULFyY6OhoAf39/vL29HVyd8ylcuPAt4698fX0pXry4xmU5yMsvv0zjxo354IMP6NixIxs3bmTKlClMmTLF0aU5pXbt2vH+++9TtmxZatSowdatWxk7dix9+/Z1dGn5mqbB56IJEybw8ccfEx0dTd26dRk/fjzh4eGOLsvpmEymDPfPmDGD3r17524xkqGWLVtqGryD/fjjj4wYMYIDBw5Qvnx5hg0bRv/+/R1dllOKj49n5MiRfPvtt5w5c4agoCC6dOnCqFGj8PDwcHR5+ZYCkIiIiDgdjQESERERp6MAJCIiIk5HAUhEREScjgKQiIiIOB0FIBEREXE6CkAiIiLidBSARERExOkoAImIZILJZOK7775zdBkikk0UgEQkz+vduzcmk+mWrzZt2ji6NBHJp9QLTETyhTZt2jBjxox0+zw9PR1UjYjkd7oCJCL5gqenJ6VKlUr3VbRoUcB6e2rixIm0bdsWb29vKlSowOLFi9M9f+fOnTz44IN4e3tTvHhxBgwYQEJCQrpjpk+fTo0aNfD09KR06dIMGTIk3ePnzp3jySefxMfHh8qVK7N06dKcfdMikmMUgESkQBg5ciRPP/0027dvp1u3bnTu3Jk9e/YAkJiYSOvWrSlatCibNm1i0aJFLF++PF3AmThxIoMHD2bAgAHs3LmTpUuXUqlSpXSvMXr0aDp27MiOHTt45JFH6NatGxcuXMjV9yki2cQQEcnjevXqZbi6uhq+vr7pvt5//33DMAwDMAYOHJjuOeHh4cagQYMMwzCMKVOmGEWLFjUSEhJsj//000+Gi4uLER0dbRiGYQQFBRlvvPHGbWsAjDfffNO2nZCQYADGL7/8km3vU0Ryj8YAiUi+0KpVKyZOnJhuX7FixWzfN2rUKN1jjRo1Ytu2bQDs2bOHOnXq4Ovra3u8SZMmWCwW9u3bh8lk4tSpUzz00EN3rKF27dq27319ffHz8+PMmTNZfUsi4kAKQCKSL/j6+t5ySyq7eHt7Z+o4d3f3dNsmkwmLxZITJYlIDtMYIBEpENavX3/LdrVq1QCoVq0a27dvJzEx0fb4mjVrcHFxoWrVqhQuXJjQ0FAiIyNztWYRcRxdARKRfCE5OZno6Oh0+9zc3ChRogQAixYton79+jRt2pQ5c+awceNGpk2bBkC3bt1466236NWrF2+//TZnz55l6NCh9OjRg8DAQADefvttBg4cSEBAAG3btiU+Pp41a9YwdOjQ3H2jIpIrFIBEJF9YtmwZpUuXTrevatWq7N27F7DO0Jo/fz7PP/88pUuXZt68eVSvXh0AHx8ffv31V1588UUaNGiAj48PTz/9NGPHjrWdq1evXiQlJfHf//6XV199lRIlStChQ4fce4MikqtMhmEYji5CRORemEwmvv32W9q3b+/oUkQkn9AYIBEREXE6CkAiIiLidDQGSETyPd3JFxF76QqQiIiIOB0FIBEREXE6CkAiIiLidBSARERExOkoAImIiIjTUQASERERp6MAJCIiIk5HAUhEREScjgKQiIiIOJ3/B4+GpErB7jkVAAAAAElFTkSuQmCC"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the Area Under Curve(AUC) of loss during training\n",
    "plt.plot(history['train_auc_1'])\n",
    "plt.plot(history['val_auc_1'])\n",
    "plt.title('Model Area Under Curve')\n",
    "plt.ylabel('Area Under Curve')\n",
    "plt.xlabel('Epoch')\n",
    "plt.legend(['Train', 'Val'], loc='upper left')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's call the evaluation function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:25.629947Z",
     "end_time": "2023-04-24T10:21:25.723946Z"
    }
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Evaluate Processing:: 100%|██████████| 8/8 [00:00<00:00, 175.93it/s, loss:0.28720757365226746 accuracy:0.8883978128433228 auc_1:0.8435608148574829]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'loss': 0.28720757, 'accuracy': 0.8883978, 'auc_1': 0.8435608}\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "global_metric = sl_model.evaluate(test_data, test_label, batch_size=128)\n",
    "print(global_metric)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Contrast to local model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Model\n",
    "The model structure is consistent with the model of split learning above, but only the model structure of Alice is used here. The model definition refers to the code below.\n",
    "#### Data\n",
    "The data also use kaggle's anti-fraud data. Here, we just use Alice's data of the new bank."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:25.722947Z",
     "end_time": "2023-04-24T10:21:27.216981Z"
    }
   },
   "outputs": [],
   "source": [
    "from tensorflow import keras\n",
    "from tensorflow.keras import layers\n",
    "import tensorflow as tf\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "def create_model():\n",
    "\n",
    "    model = keras.Sequential(\n",
    "        [\n",
    "            keras.Input(shape=4),\n",
    "            layers.Dense(100,activation =\"relu\" ),\n",
    "            layers.Dense(64, activation='relu'),\n",
    "            layers.Dense(64, activation='relu'),\n",
    "            layers.Dense(1, activation='sigmoid')\n",
    "        ]\n",
    "    )\n",
    "    model.compile(loss='binary_crossentropy',\n",
    "                      optimizer='adam',\n",
    "                      metrics=[\"accuracy\",tf.keras.metrics.AUC()])\n",
    "    return model\n",
    "\n",
    "single_model = create_model()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "data process"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:27.215974Z",
     "end_time": "2023-04-24T10:21:27.277974Z"
    }
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "\n",
    "encoder = LabelEncoder()\n",
    "single_part_data = alice_data.copy()\n",
    "\n",
    "single_part_data['job'] = encoder.fit_transform(alice_data['job'])\n",
    "single_part_data['marital'] = encoder.fit_transform(alice_data['marital'])\n",
    "single_part_data['education'] = encoder.fit_transform(alice_data['education'])\n",
    "single_part_data['y'] =  encoder.fit_transform(alice_data['y'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:27.273977Z",
     "end_time": "2023-04-24T10:21:27.353010Z"
    }
   },
   "outputs": [],
   "source": [
    "single_part_label = single_part_data['y']\n",
    "single_part_data_no_label = single_part_data.drop(columns=['y'],inplace=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:27.369974Z",
     "end_time": "2023-04-24T10:21:27.443023Z"
    }
   },
   "outputs": [],
   "source": [
    "scaler = MinMaxScaler()\n",
    "single_part_data_no_label = scaler.fit_transform(single_part_data_no_label)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:27.433998Z",
     "end_time": "2023-04-24T10:21:27.468026Z"
    }
   },
   "outputs": [],
   "source": [
    "train_data,test_data = train_test_split(single_part_data_no_label, train_size=0.8,random_state=random_state)\n",
    "train_label,test_label = train_test_split(single_part_label, train_size=0.8,random_state=random_state)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:27.459034Z",
     "end_time": "2023-04-24T10:21:27.496008Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": "(905, 4)"
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "ExecuteTime": {
     "start_time": "2023-04-24T10:21:27.482973Z",
     "end_time": "2023-04-24T10:21:30.586951Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n",
      "29/29 [==============================] - 2s 13ms/step - loss: 0.5258 - accuracy: 0.8653 - auc_3: 0.4494 - val_loss: 0.4046 - val_accuracy: 0.8729 - val_auc_3: 0.4320\n",
      "Epoch 2/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3747 - accuracy: 0.8877 - auc_3: 0.4590 - val_loss: 0.4003 - val_accuracy: 0.8729 - val_auc_3: 0.4279\n",
      "Epoch 3/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3684 - accuracy: 0.8877 - auc_3: 0.4383 - val_loss: 0.3941 - val_accuracy: 0.8729 - val_auc_3: 0.4223\n",
      "Epoch 4/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3623 - accuracy: 0.8877 - auc_3: 0.4465 - val_loss: 0.3904 - val_accuracy: 0.8729 - val_auc_3: 0.4248\n",
      "Epoch 5/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3600 - accuracy: 0.8877 - auc_3: 0.4533 - val_loss: 0.3877 - val_accuracy: 0.8729 - val_auc_3: 0.4401\n",
      "Epoch 6/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3578 - accuracy: 0.8877 - auc_3: 0.4655 - val_loss: 0.3857 - val_accuracy: 0.8729 - val_auc_3: 0.4659\n",
      "Epoch 7/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3562 - accuracy: 0.8877 - auc_3: 0.4869 - val_loss: 0.3841 - val_accuracy: 0.8729 - val_auc_3: 0.4851\n",
      "Epoch 8/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3550 - accuracy: 0.8877 - auc_3: 0.4975 - val_loss: 0.3828 - val_accuracy: 0.8729 - val_auc_3: 0.4969\n",
      "Epoch 9/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3539 - accuracy: 0.8877 - auc_3: 0.5105 - val_loss: 0.3816 - val_accuracy: 0.8729 - val_auc_3: 0.5166\n",
      "Epoch 10/10\n",
      "29/29 [==============================] - 0s 4ms/step - loss: 0.3528 - accuracy: 0.8877 - auc_3: 0.5216 - val_loss: 0.3807 - val_accuracy: 0.8729 - val_auc_3: 0.5241\n"
     ]
    }
   ],
   "source": [
    "history =single_model.fit(train_data,train_label,validation_data=(test_data,test_label),batch_size=128,epochs=10,shuffle=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "Referring to the above visualization code, the training process of a local model can also be visualized"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Summary\n",
    "The above two experiments simulate a typical vertical scene training problem. Alice and Bob have the same sample group, but each side has only a part of the features. If Alice only uses her own data to train the model, an accuracy of **0.8729**, AUC **0.5241** model can be obtained. However, if Bob's data are combined, a model with an accuracy of **0.8884**  and AUC **0.8436** can be obtained."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* This tutorial introduces what is split learning and how to do it in secretFlow  \n",
    "* It can be seen from the experimental data that split learning has significant advantages in expanding sample dimension and improving model effect through joint multi-party training\n",
    "* This tutorial uses plaintext aggregation to demonstrate, without considering the leakage problem of hidden layer. Secretflow provides AggLayer to avoid the leakage problem of hidden layer plaintext transmission through MPC,TEE,HE, and DP. If you are interested, please refer to relevant documents.\n",
    "* Next, you may want to try different data sets, you need to vertically shard the data first and then follow the flow of this tutorial\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.8.13 ('3.8')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.13"
  },
  "vscode": {
   "interpreter": {
    "hash": "ae1fdd5fd034b7d694352220485921694ff89198520409089b4646721fce11ca"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
